package com.yuan.util.image;

import com.yuan.util.date.DateUtil;
import com.yuan.util.string.StrUtil;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * Explain:     [图片工具类]
 * Date:        [2017/7/4 17:32]
 * Coder:       [YouYuan]
 * Version:     [1.0]
 */
public class ImageUtil {

    public static final String DEFAULT_SUFFIX = ".jpg";//默认后缀
    public static final int AUTO_ADAPTION = -1;//自适应宽高
    public static final int SCALE_FAST = Image.SCALE_FAST;//快速压缩
    public static final int SCALE_SMOOTH = Image.SCALE_SMOOTH;//平滑压缩

    public static void main(String[] args) throws Exception {
//        BufferedImage image = cutImage("F:\\Photos\\未加密\\梦璃.jpeg", 800, 200, 800, 800);
//        saveImage(image, "F:\\Temp\\");
//        BufferedImage zoomImage = zoomImage("F:/Photos/未加密/梦璃.jpeg", AUTO_ADAPTION, 50, ImageUtil.SCALE_SMOOTH);
//        saveImage(zoomImage, "F:/Temp/", null);
        BufferedImage zoomImageBySize = zoomImage("F:\\Photos\\软件相关/大前端知识架构.png", 2100);
        saveImage(zoomImageBySize, "F:/Temp/", null);
    }

    public static BufferedImage cutImage(String srcPath, int startX, int startY, int width, int height) throws Exception {
        BufferedImage image = ImageIO.read(new File(srcPath));
        return cutImage(image, startX, startY, width, height);
    }

    public static BufferedImage cutImage(File imgFile, int startX, int startY, int width, int height) throws Exception {
        BufferedImage image = ImageIO.read(imgFile);
        return cutImage(image, startX, startY, width, height);
    }

    /**
     * 裁剪图片
     *
     * @param image  图片对象
     * @param startX 指定矩形区域左上角的 X 坐标
     * @param startY 指定矩形区域左上角的 Y 坐标
     * @param width  指定矩形区域的宽度
     * @param height 指定矩形区域的高度
     * @return
     */
    public static BufferedImage cutImage(BufferedImage image, int startX, int startY, int width, int height) {
        if (image != null) {
            return image.getSubimage(startX, startY, width, height);
        }
        return null;
    }

    /**
     * 生成默认图片名
     *
     * @return
     */
    public static String generateImgName() {
        return DateUtil.getNowNumberDate() + "-" + StrUtil.uuid() + DEFAULT_SUFFIX;
    }

    /**
     * 保存图片到指定路径,如果图片宽高与设定值不匹配的话压缩图片为指定宽高
     *
     * @param image   图片对象
     * @param imgName 图片名
     * @param tarPath 保存目标路径
     * @param width   图片宽
     * @param height  图片高
     * @throws IOException
     */
    public static void saveImage(BufferedImage image, String imgName, String tarPath, int width, int height) throws Exception {
        if (StrUtil.isEmpty(imgName)) {
            imgName = generateImgName();
        }
        if (image.getWidth() != width || image.getHeight() != height) {
            BufferedImage tempImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            tempImg.getGraphics().drawImage(image.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null);
            ImageIO.write(tempImg, null, new File(tarPath + "/" + imgName));
        } else {
            ImageIO.write(image, null, new File(tarPath + "/" + imgName));
        }
    }

    /**
     * 保存图片到指定路径
     *
     * @param image
     * @param tarPath
     * @param imgName
     * @throws IOException
     */
    public static void saveImage(BufferedImage image, String tarPath, String imgName) throws Exception {
        if (StrUtil.isEmpty(imgName)) {
            imgName = generateImgName();
        }
        ImageIO.write(image, "jpg", new File(tarPath + "/" + imgName));
    }

    public static BufferedImage zoomImage(String srcPath, int width, int height, int scaleType) throws Exception {
        File srcFile = new File(srcPath);
        BufferedImage bufImg = ImageIO.read(srcFile); //读取图片
        return zoomImage(bufImg, width, height, scaleType);
    }

    /**
     * 压缩图片
     *
     * @param img       图片对象
     * @param width     目标宽
     * @param height    目标高
     * @param scaleType 压缩类型(快速Image.SCALE_FAST/平滑Image.SCALE_SMOOTH)
     * @return
     * @throws Exception
     */
    public static BufferedImage zoomImage(BufferedImage img, int width, int height, int scaleType) throws Exception {
        if (img != null) {
            double newWidth, newHeight;
            int rawWidth = img.getWidth();
            int rawHeight = img.getHeight();
            if (width == ImageUtil.AUTO_ADAPTION && height >= 0) {
                newHeight = height;
                newWidth = rawWidth * newHeight / rawHeight;//自动等比例宽度
            } else if (height == ImageUtil.AUTO_ADAPTION && width >= 0) {
                newWidth = width;
                newHeight = rawHeight * newWidth / rawWidth;//自动等比例高度
            } else if (width >= 0 && height >= 0) {
                newWidth = width;
                newHeight = height;
            } else {
                throw new Exception("长度和宽度不合法");
            }
            Image zoomImg = img.getScaledInstance((int) newWidth, (int) newHeight, scaleType);//方式1:Image压缩
//            AffineTransformOp ato = new AffineTransformOp(AffineTransform.getScaleInstance(newWidth / rawWidth, newHeight / rawHeight), null);
//            Image Itemp = ato.filter(img, null);//方式2:过滤压缩
//            return (BufferedImage) Itemp;
            return imageToBufferedImage(zoomImg);
        }
        return null;
    }

    /**
     * 按照文件大小对图片进行缩放
     * @param src 图片路径
     * @param size 限制大小,以K为单位,为0输出原图
     * @return
     * @throws Exception
     */
    public static BufferedImage zoomImage(String src, Integer size) throws Exception {
        if (size == null || size < 0) {
            throw new Exception("Size不能小于0");
        }
        File srcFile = new File(src);
        return zoomImage(srcFile, size);
    }

    /**
     * 按照文件大小对图片进行缩放
     * @param srcFile 图片文件对象
     * @param size 限制大小,以K为单位,为0输出原图
     * @return
     * @throws Exception
     */
    public static BufferedImage zoomImage(File srcFile, Integer size) throws Exception {
        if (size == null || size < 0) {
            throw new Exception("Size不能小于0");
        }
        BufferedImage img = ImageIO.read(srcFile);
        if (img == null) {
            throw new RuntimeException("不支持的图片格式");
        }
        double newSize = size * 1024;
        double rawSize = srcFile.length();
        if (rawSize < newSize || newSize == 0) {   //文件大于size k时，才进行缩放,注意：size以K为单位
            return imageToBufferedImage(img);
        }
//        Double rate = (rawSize / size) / 2.0 * 1.1; // 获取长宽缩放比例
        double newWidth, newHeight;
        double rawWidth = img.getWidth();
        double rawHeight = img.getHeight();
//        newHeight = Math.sqrt(size * rawWidth / rawHeight);//根据原宽高比例缩放
//        newWidth = newHeight * rawWidth / rawHeight;
        double repairScale;//大小修正比例
        if (size > 200) {
            repairScale = 0.999;
        } else if (size >= 150) {
            repairScale = 0.983;
        } else if (size >= 100) {
            repairScale = 0.972;
        } else {
            repairScale = 0.90;
        }
        newHeight = Math.sqrt(rawWidth * rawHeight / (rawSize / newSize * rawWidth / rawHeight)) * repairScale;//根据大小比例缩放
        newWidth = rawWidth * newHeight / rawHeight * repairScale;
        Image zoomImg = img.getScaledInstance((int) newWidth, (int) newHeight, Image.SCALE_SMOOTH);
        return imageToBufferedImage(zoomImg);
    }

    /**
     * 将Image对象转换为BufferedImage
     *
     * @param image
     * @return
     */
    public static BufferedImage imageToBufferedImage(Image image) {
        if (image == null) {
            return null;
        }
        BufferedImage newImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
        Graphics2D g = newImage.createGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return newImage;
    }

}
